#include <cmath>
#include <assert.h>
#include <limits>

#include "Box.h"

bool Box::intersectLocal( const ray& r, isect& i ) const
{
	// YOUR CODE HERE:
    // Add box intersection code here.
	// it currently ignores all boxes and just returns false.

	// We perform something similar to the SQUARE intersection, but for all 6 sides. 
	// Box is assumed to have x, y, z coordinates +-0.5

	vec3f p = r.getPosition();
	vec3f d = r.getDirection();

	bool has_intersect = false;
	float best_dist = std::numeric_limits<float>::infinity();

	for (int dim = 0; dim < 3; dim++) { // Loop through the x,y,z parameters. eg, dim = 0 means the 2 planes have normals parallel to (1, 0, 0)
		
		// degenerate case where we are parallel to the face
		if (d[dim] == 0) continue; // We use '==' here just to prevent division by 0

		// get intersection points with -0.5 and 0.5
		for (float ints = -0.5; ints < 0.6; ints += 1.0f) {
			
			// p[dim] + d[dim] * t = -0.5 or 0.5
			float t = (ints - p[dim])/d[dim];

			// compute intersection point!
			vec3f intp = r.at(t);
			// cout << intp[0] << "," << intp[1] << "," << intp[2] << endl;
			// cout << intp[dim] << endl;

			bool isIntersect = true;
			// check for bounds for each of the 2 dimensions that is not == dim
			for (int a = 0; a < 3; a++) {
				if (dim == a) continue;
				if (intp[a] < -0.5f || intp[a] > 0.5f) {
					isIntersect = false; 
				}
			}

			vec3f normal(0.0f, 0.0f, 0.0f);
			if (isIntersect && t < best_dist && t > RAY_EPSILON) {

				if (d[dim] > 0.0f) {
					normal[dim] = -1.0f;
				}else{
					normal[dim] = 1.0f;
				}

				i.obj = this;
				i.t = t;
				i.N = normal;
				has_intersect = true;

				best_dist = t;
			}
		}
	}


	return has_intersect;
}
